

// --- Programme Arduino ---
// Modification Stéphane LARSON - 
// Ajout de plusieurs types de capteurs, 

// Copyright X. HINAULT - Créé le 11/04/2010
// www.mon-club-elec.fr 

//  Code sous licence GNU GPL : 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License,
//  or any later version.
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//  

// --- Circuit à réaliser ---
// Connexion série entre la carte Arduino et le PC (utilise les broches 0 et 1)  
// Connecter  sur la broche 2 la broche de données du capteur One Wire (Numérique)
// Pour la partie analogique voir le diagramme fritzing

#include <OneWire.h> // librairie pour capteur OneWire
//#include <MsTimer2.h>

#define MAX_ONE_WIRE 8

// --- Déclaration des constantes ---
//28 26 EF BB 03 00 00 4E
//---- code des instructions du capteur
const int modeLecture=0xBE;
const int lancerMesure=0x44;

// --- constantes des broches ---

const int broche_OneWire=2; 
const int broche_lumiere=A0;
const int broche_lumiere2=A1;

// --- Déclaration des variables globales ---
byte data[12]; // Tableau de 12 octets pour lecture des 9 registres de RAM et des 3 registres d'EEPROM du capteur One Wire
byte adresses[MAX_ONE_WIRE][8]; // Tableau de 8 octets pour stockage du code d'adresse 64 bits du composant One Wire, un par OneWire Dispo sur le réseau
byte adresse[8]; // Tableau de 8 octets pour stockage du code d'adresse 64 bits du composant One Wire

// --- Déclaration des objets utiles pour les fonctionnalités utilisées ---
OneWire  capteur(broche_OneWire);  // crée un objet One Wire sur la broche voulue

int delais = 30000;
int nbCapteurs = 0;

unsigned long curMillis;
unsigned long oldMillis = 0;

void setup()   
{ 
  Serial.begin(115200); // initialise connexion série à 115200 bauds
  // --- initialisation du capteur DS18B20 ------
  capteurInit(); // appel de la fonction d'initialisation du capteur - au début seulement 
                // prise en compte des capteurs trouvés dans le tableau des adresses
/*
  MsTimer2::set( delais, captureData );
  MsTimer2::start();
*/
} 


void captureData()
{
    unsigned int sensorValue = 0;
    sensorValue = analogRead(broche_lumiere); 
    Serial.print( "D" );
    Serial.print( millis() );
    Serial.print(",");
    Serial.print( sensorValue);

    sensorValue = analogRead(broche_lumiere2); 
    Serial.print(",");
    Serial.print( sensorValue);

    for ( int i=0; i < nbCapteurs; i++ )
    {
      Serial.print(",");
      Serial.print ( capteurMesureTemp(i), 2 );
    }
    Serial.println("");

}

//*************** FONCTION LOOP = Boucle sans fin = coeur du programme *************
// la fonction loop() s'exécute sans fin en boucle aussi longtemps que l'Arduino est sous tension

void loop()
{ 
  // Rien a faire ici tout est géré en interruption

    curMillis = millis();

  if ( ( curMillis - oldMillis ) > delais )
  {
    captureData();
    oldMillis = curMillis - ( curMillis % 1000);
  }
} 

//************************** fonction d'initialisation du capteur ****************
void capteurInit()
{
  Serial.println("**** Detection du capteur **** "); 

  nbCapteurs = 0;
  while ( nbCapteurs == 0 )
  {
    // la fonction search renvoie la valeur VRAI si un élément 1-wire est trouvé.
    // la fonction search renvoie la valeur FAUX si aucun autre élément 1-wire est trouvé. 
    // Stocke son code d'adresse dans le tableau adresses
    while ( capteur.search( adresses[nbCapteurs] ) != false ) // tant qu'aucun nouveau capteur n'est détecté
    {
      
      nbCapteurs ++;
    }
    
    if ( nbCapteurs == 0)
    {
      Serial.println("** Aucun capteur 1-wire present sur la broche ! **"); 
      delay (1000); // pause 1 seconde
    }
    else
    {

      Serial.println ("** capteur 1-wire present avec code adresse 64 bits : **");


      for ( int idxCapteur = 0; idxCapteur < nbCapteurs; idxCapteur++) 
      {   
        Serial.print("** ");
        //--- affichage des 64 bits d'adresse au format hexadécimal
        for(int i = 0; i < 8; i++) 
        {

          if ( adresses[idxCapteur][i] < 16 ) 
          { 
            Serial.print("0"); 
          } 
          Serial.print( adresses[idxCapteur][i], HEX ); // affiche 1 à 1 les 8 octets du tableau adresse au format hexadécimal
          Serial.print(" ");
        }
        switch ( adresses[idxCapteur][0] )
        {
          case 0x28 : Serial.print (" Capteur temperature DS18B20.");break;
          case 0x10 : Serial.print (" Capteur temperature DS18S20.");break; 
          case 0x22 : Serial.print (" Capteur temperature DS1820.");break;
        }
        
        //----- contrôle du code CRC ----
        // le dernier octet de l'adresse 64bits est un code de contrôle CRC 
        // à l'aide de la fonction crc8 on peut vérifier si ce code est valide
        if (capteur.crc8( adresses[idxCapteur], 7) == adresses[idxCapteur][7]) // vérification validité code CRC de l'adresse 64 bits
        // le code CRC de l'adresse 64 bits est le 8ème octet de l'adresse (index 7 du tableau)
        {
          Serial.print ("CRC OK"); 
        }
        else
        {
          Serial.print ("CRC KO");     
        }
                
         
        Serial.println(" **");        
      }   
    }
  }
  
  // Test : Je prends en compte le premier uniquement
/*  
  for (int i = 0; i < 8; i++)
  {
    adresse[i] = adresses[ 0 ][i];
  }
          Serial.print("** ");        
  for(int i = 0; i < 8; i++) 
        {

          if ( adresse[i] < 16 ) 
          { 
            Serial.print("0"); 
          } 
          Serial.print( adresse[i], HEX ); // affiche 1 à 1 les 8 octets du tableau adresse au format hexadécimal
          Serial.print(" ");
        }
          Serial.println(" **");
*/          
  //------- message final détection ---- 
  Serial.println("***** fin de la recherche des capteurs *****"); 

}
//----------- fin de la fonction d'initialisation du capteur ---------- 


float capteurMesureTempLegacy() 
{ 
   //-------- variable locale de la fonction ---------- 
  int tempet=0; // variable pour resultat brute  de la mesure
  float tempetf=0.0; // variable pour resultat à virgule de la mesure
 // Serial.println("**** Acquisition d'une mesure de la temperature **** "); 

  // avant chaque nouvelle instruction, il faut : 
  //    * initialiser le bus 1-wire
  //    * sélectionner le capteur détecté
  //    * envoyer l'instruction 

  //--------- lancer une mesure --------
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  capteur.select(adresse); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
  capteur.write(lancerMesure,1); // lance la mesure et alimente le capteur par la broche de donnée

  //-------- pause d'une seconde ----- 
  // Utilisation de delayMicrosconds au lieu de delay, il semblerait que ce dernier ait un soucis avec la librairie MsTimer2
  delay(1000);     // au moins 750 ms
  // il faudrait mettre une instruction capteur.depower ici, mais le reset va le faire

  //---------- passer en mode LECTURE ------------- 
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  capteur.select(adresse); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
  capteur.write(modeLecture,1); // passe en mode lecture de la RAM du capteur

  // ----------- lire les 9 octets de la RAM (appelé Scratchpad) ----

  for ( int i = 0; i < 9; i++) {           // 9 octets de RAM stockés dans 9 octets
    data[i] = capteur.read();             // lecture de l'octet de rang i stocké dans tableau data
  }
  //----- caclul de la température mesurée (enfin!) ---------

  data[1]=data[1] & B10000111; // met à 0 les bits de signes inutiles
  tempet=data[1]; // bits de poids fort
  tempet=tempet<<8; 
  tempet=tempet+data[0]; // bits de poids faible

  // --- en mode 12 bits, la résolution est de 0.0625°C - cf datasheet DS18B20
  tempetf=float(tempet)*6.25;
  tempetf=tempetf/100.0;

  return (tempetf);

}

//-------------- fonction de mesure de la température --------------- 
float capteurMesureTemp( int idxCapteur ) 
{ 
   //-------- variable locale de la fonction ---------- 
  int tempet=0; // variable pour resultat brute  de la mesure
  float tempetf=0.0; // variable pour resultat à virgule de la mesure
  // avant chaque nouvelle instruction, il faut : 
  //    * initialiser le bus 1-wire
  //    * sélectionner le capteur détecté
  //    * envoyer l'instruction 

  //--------- lancer une mesure --------
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  capteur.select(adresses[idxCapteur]); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
  capteur.write(lancerMesure,1); // lance la mesure et alimente le capteur par la broche de donnée

  //-------- pause d'une seconde ----- 
  // Utilisation de delayMicrosconds au lieu de delay, il semblerait que ce dernier ait un soucis avec la librairie MsTimer2
  delay(1000);     // au moins 750 ms
  // il faudrait mettre une instruction capteur.depower ici, mais le reset va le faire

  //---------- passer en mode LECTURE ------------- 
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  capteur.select(adresses[idxCapteur]); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
  capteur.write(modeLecture,1); // passe en mode lecture de la RAM du capteur

  // ----------- lire les 9 octets de la RAM (appelé Scratchpad) ----
  for ( int i = 0; i < 9; i++) 
  {           
    data[i] = capteur.read();
  }
  //----- caclul de la température mesurée (enfin!) ---------

  data[1] = data[1] & B10000111; // met à 0 les bits de signes inutiles
  tempet = data[1]; // bits de poids fort
  tempet = tempet << 8; 
  tempet = tempet + data[0]; // bits de poids faible

  // --- en mode 12 bits, la résolution est de 0.0625°C - cf datasheet DS18B20
  tempetf = float(tempet)*6.25;
  tempetf = tempetf / 100.0;

  return (tempetf);

}

//-------------- fonction de mesure de la température --------------- 
float * lectureTousCapteurMesureTemp( ) 
{ 
   //-------- variable locale de la fonction ---------- 
  int tempet=0; // variable pour resultat brute  de la mesure
  float tempetf[MAX_ONE_WIRE];
  // avant chaque nouvelle instruction, il faut : 
  //    * initialiser le bus 1-wire
  //    * sélectionner le capteur détecté
  //    * envoyer l'instruction 

  //--------- lancer une mesure --------
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  
  for ( int idxCapteur=0; idxCapteur < nbCapteurs; idxCapteur ++)
  {
    capteur.select(adresses[idxCapteur]); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
    capteur.write(lancerMesure,1); // lance la mesure et alimente le capteur par la broche de donnée
  }
  

  //-------- pause d'une seconde ----- 
  // Utilisation de delayMicrosconds au lieu de delay, il semblerait que ce dernier ait un soucis avec la librairie MsTimer2
  delayMicroseconds(1000000);     // au moins 750 ms
  // il faudrait mettre une instruction capteur.depower ici, mais le reset va le faire
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  for ( int idxCapteur=0; idxCapteur < nbCapteurs; idxCapteur ++)
  {
    capteur.select(adresses[idxCapteur]); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
    capteur.write(modeLecture,1); // lance la mesure et alimente le capteur par la broche de donnée
    // ----------- lire les 9 octets de la RAM (appelé Scratchpad) ----
    for ( int i = 0; i < 9; i++) 
    {           
      data[i] = capteur.read();
    }

    //----- caclul de la température mesurée (enfin!) ---------
  
    data[1] = data[1] & B10000111; // met à 0 les bits de signes inutiles
    tempet = data[1]; // bits de poids fort
    tempet = tempet << 8; 
    tempet = tempet + data[0]; // bits de poids faible
  
    // --- en mode 12 bits, la résolution est de 0.0625°C - cf datasheet DS18B20
    tempetf[idxCapteur] = float(tempet)*0.0625;

  }

  return (tempetf);

}


// --- Fin programme ---
